package org.zcl.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.zcl.entity.User;
import org.zcl.feign.ProducerClient;

/**
 * @Package org.zcl.controller
 * @PROJECT_NAME: hystrix-demo
 * @DESCRIPTION:
 * @USER: zhuchenglin
 * @DATE: 2022/2/8 15:24
 */
@RestController
@Slf4j
public class ConsumerController {

    private final static String service_producer_name = "PRODUCER";

    @Autowired
    private ProducerClient producerClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping(value = "feignTest")
    @HystrixCommand(
            threadPoolKey = "feignTestTimeOut",
            fallbackMethod = "testHystrix")
    public String feignTest(String name, Integer mills) {
        log.info("开始请求 producer，其暂停时间为：" + mills);
        String producerRes = producerClient.hello(name, mills);
        log.info("请求获取成功，开始打印请求结果：");
        return producerRes;
    }

    @GetMapping(value = "test")
    @HystrixCommand(
            // 属性配置HystrixCommandProperties
            commandProperties = {
                    // 是否在超时发生时被中断
                    @HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout",value = "2000"),
                    // 熔断时间窗
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "8000"),
                    // 最小请求次数
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),
                    // 阈值百分比
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
                    // 跳闸活动时长
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")
            },

            threadPoolKey = "testTimeOut",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "2"), // 线程数
                    @HystrixProperty(name = "maxQueueSize", value = "20") // 等待队列长度
            },
            fallbackMethod = "testHystrix")
    public String test(String name, Integer mills) {
        log.info("开始请求 producer，其暂停时间为：" + mills);
        String producerRes = restTemplate.getForObject(
                "http://" + service_producer_name + "/hello/" + name + "?mills=" + mills, String.class);
        log.info("请求获取成功，开始打印请求结果：");
        return producerRes;
    }

    public String testHystrix(String name, Integer mills, Throwable throwable) {
        log.info("[testHystrix][name({}) mills({}) exception({})]", name, mills, ExceptionUtils.getRootCauseMessage(throwable));
        return "failure";
    }

    @PostMapping(value = "add")
    public String add(@RequestBody User user) {
        return producerClient.add(user);
    }
}
